[VTD] Utilise the snoop control capability in shadow with VT-d code
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 20 Feb 2009 11:11:40 +0000 (11:11 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 20 Feb 2009 11:11:40 +0000 (11:11 +0000)
We compute the shadow PAT index in leaf page entries now as:
1) No VT-d assigned: let shadow PAT index as WB, handled already
in shadow code before.
2) direct assigned MMIO area: let shadow code compute the shadow
PAT with gMTRR=UC and gPAT value.
3) Snoop control enable: let shadow PAT index as WB.
4) Snoop control disable:  let shadow code compute the shadow
PAT with gMTRR and gPAT, handled already in shadow code before

Signed-off-by: Xin, Xiaohui <xiaohui.xin@intel.com>
xen/arch/x86/hvm/mtrr.c
xen/arch/x86/mm/shadow/multi.c
xen/include/asm-x86/mtrr.h

index 6f64062cf9c0f3c9192e6c3cb2998869bfc8d21e..e1448d99ee99bab6afc1fc32e05f835ed1e28e65 100644 (file)
@@ -351,11 +351,18 @@ static uint8_t page_pat_type(uint64_t pat_cr, uint32_t pte_flags)
 static uint8_t effective_mm_type(struct mtrr_state *m,
                                  uint64_t pat,
                                  paddr_t gpa,
-                                 uint32_t pte_flags)
+                                 uint32_t pte_flags,
+                                 uint8_t gmtrr_mtype)
 {
     uint8_t mtrr_mtype, pat_value, effective;
-
-    mtrr_mtype = get_mtrr_type(m, gpa);
+   
+    /* if get_pat_flags() gives a dedicated MTRR type,
+     * just use it
+     */ 
+    if ( gmtrr_mtype == NO_HARDCODE_MEM_TYPE )
+        mtrr_mtype = get_mtrr_type(m, gpa);
+    else
+        mtrr_mtype = gmtrr_mtype;
 
     pat_value = page_pat_type(pat, pte_flags);
 
@@ -367,7 +374,8 @@ static uint8_t effective_mm_type(struct mtrr_state *m,
 uint32_t get_pat_flags(struct vcpu *v,
                        uint32_t gl1e_flags,
                        paddr_t gpaddr,
-                       paddr_t spaddr)
+                       paddr_t spaddr,
+                       uint8_t gmtrr_mtype)
 {
     uint8_t guest_eff_mm_type;
     uint8_t shadow_mtrr_type;
@@ -378,7 +386,8 @@ uint32_t get_pat_flags(struct vcpu *v,
     /* 1. Get the effective memory type of guest physical address,
      * with the pair of guest MTRR and PAT
      */
-    guest_eff_mm_type = effective_mm_type(g, pat, gpaddr, gl1e_flags);
+    guest_eff_mm_type = effective_mm_type(g, pat, gpaddr, 
+                                          gl1e_flags, gmtrr_mtype);
     /* 2. Get the memory type of host physical address, with MTRR */
     shadow_mtrr_type = get_mtrr_type(&mtrr_state, spaddr);
 
index 51566b2eb3dc409121333cf95596646f7c330fa4..56fc5635e4afaa987a743417d76cd8f385e5263f 100644 (file)
@@ -546,15 +546,32 @@ _sh_propagate(struct vcpu *v,
          !is_xen_heap_mfn(mfn_x(target_mfn)) )
     {
         unsigned int type;
+
+        /* compute the PAT index for shadow page entry when VT-d is enabled
+         * and device assigned. 
+         * 1) direct MMIO: compute the PAT index with gMTRR=UC and gPAT.
+         * 2) if enables snoop control, compute the PAT index as WB.
+         * 3) if disables snoop control, compute the PAT index with
+         *    gMTRR and gPAT.
+         */
         if ( hvm_get_mem_pinned_cacheattr(d, gfn_x(target_gfn), &type) )
             sflags |= pat_type_2_pte_flags(type);
         else if ( d->arch.hvm_domain.is_in_uc_mode )
             sflags |= pat_type_2_pte_flags(PAT_TYPE_UNCACHABLE);
+        else if ( p2mt == p2m_mmio_direct )
+            sflags |= get_pat_flags(v,
+                                    gflags,
+                                    gfn_to_paddr(target_gfn),
+                                    ((paddr_t)mfn_x(target_mfn)) << PAGE_SHIFT,
+                                    MTRR_TYPE_UNCACHABLE); 
+        else if ( iommu_snoop )
+            sflags |= pat_type_2_pte_flags(PAT_TYPE_WRBACK);
         else
             sflags |= get_pat_flags(v,
                                     gflags,
                                     gfn_to_paddr(target_gfn),
-                                    ((paddr_t)mfn_x(target_mfn)) << PAGE_SHIFT);
+                                    ((paddr_t)mfn_x(target_mfn)) << PAGE_SHIFT,
+                                    NO_HARDCODE_MEM_TYPE);
     }
 
     // Set the A&D bits for higher level shadows.
index 65d56f7d8ede56afd2e4c777079c928cf9cbf8df..03285db5bda71b2f91c3509a2e3e32952de8b8cc 100644 (file)
@@ -11,6 +11,7 @@
 #define MTRR_TYPE_WRBACK     6
 #define MTRR_NUM_TYPES       7
 #define MEMORY_NUM_TYPES     MTRR_NUM_TYPES
+#define NO_HARDCODE_MEM_TYPE    MTRR_NUM_TYPES
 
 #define NORMAL_CACHE_MODE          0
 #define NO_FILL_CACHE_MODE         2
@@ -63,7 +64,7 @@ extern int mtrr_del(int reg, unsigned long base, unsigned long size);
 extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
 extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
 extern u32 get_pat_flags(struct vcpu *v, u32 gl1e_flags, paddr_t gpaddr,
-                  paddr_t spaddr);
+                  paddr_t spaddr, uint8_t gmtrr_mtype);
 extern uint8_t epte_get_entry_emt(
     struct domain *d, unsigned long gfn, unsigned long mfn,
     uint8_t *igmt, int direct_mmio);